# encoding:utf-8
from base import (dingding_push, read4csv, get_rates4pos, generate_data, write_2csv, initialize_mt5,
                  conversion_tradetime, judge_price4value, judge_Kline_color)
from datetime import datetime
import MetaTrader5 as mt5
import pandas as pd
import yaml, time
import numpy as np

# pd.options.mode.copy_on_write = True

def count_numbers(a, b, c):
    """完整统计正数、负数和零的数量"""
    nums = [a, b, c]
    pos = sum(1 for num in nums if num > 0)
    neg = sum(1 for num in nums if num < 0)
    zero = sum(1 for num in nums if num == 0)
    return pos, neg, zero

def check_price_away_bollinger(df_data,lookback_period=3):
    '''lookback_period# 回溯周期，用于判断趋势，默认为3'''
    # 检查最近lookback_period期的距离变化趋势
    recent_distances = df_data.dropna().tail(lookback_period)
    # 判断距离是否越来越大（正值越来越大表示价格高于下轨且距离扩大）
    if len(recent_distances) >= 2:
        # 计算距离变化率
        changes = np.diff(recent_distances)


        # 如果所有变化都为正（距离越来越大）
        is_increasing_distance = all(c > 0 for c in changes)

        # 或者使用线性回归判断趋势
        # x = np.arange(len(recent_distances))
        # slope = np.polyfit(x, recent_distances, 1)[0]
        # is_increasing_distance = slope > 0

        return is_increasing_distance
    else:
        return False

with open('config.yaml', 'r', encoding='utf-8') as f:
    config = yaml.safe_load(f)
    run_mod = config['run_mod']
    begin = config['begin']
    symbol = config['symbol']
    min_level = config['level']['min_level']
    mid_level = config['level']['mid_level']
    large_level = config['level']['lar_level']
    level_str = config['level']['title']

begin_time = datetime.strptime(begin, "%Y.%m.%d %H:%M:%S")
i = 0
now = ''
price = ''
test_time = datetime.now().strftime("%Y.%m.%d %H:%M:%S")
if run_mod == 'test':
    lar_df = read4csv(symbol, large_level)
    mid_df = read4csv(symbol, mid_level)
    min_df = read4csv(symbol, min_level)

while True:
    if run_mod != 'test':
        now = datetime.now()
        if now.weekday() >= 5:
            # 跳过周末
            continue
        if mt5.terminal_info() == None:
            initialize_mt5()
            print("执行MT5初始化！")
        lasttick = mt5.symbol_info_tick(symbol)._asdict()  # 以列表的形式显示报价字段值
        lasttick_bid = lasttick['bid']
        lasttick_ask = lasttick['ask']
        price = lasttick_ask  # 检测价格设置买入价

        # 生成数据
        base_number = 1000  # 十年521周
        # 生成大周期数据
        for level in (min_level, mid_level, large_level):  # 15,60,240,1440,7200
            if level == large_level:
                k_number = base_number
            elif level == mid_level:
                k_number = base_number * 5
            elif level == min_level:
                k_number = base_number * 5 * 5
            else:
                k_number = base_number
            rates_df = get_rates4pos(symbol, level, 0, k_number)
            tem_rates_df = rates_df[['time', 'open', 'high', 'low', 'close', 'tick_volume']]
            gen_df = generate_data(tem_rates_df)
            write_2csv(gen_df, symbol, level)
        min_target_df = min_df = read4csv(symbol, min_level)
        mid_target_df = mid_df = read4csv(symbol, mid_level)
        lar_target_df = lar_df = read4csv(symbol, large_level)
        now = now.strftime('%Y.%m.%d %H:%M:%S')

    elif run_mod == 'test':
        test_time = begin_time + pd.Timedelta(minutes=mid_level * i)
        i += 1
        if test_time.weekday() >= 5:
            # 跳过周末
            continue
        min_test_time = conversion_tradetime(test_time, min_level)
        mid_test_time = conversion_tradetime(test_time, mid_level)
        lar_test_time = conversion_tradetime(test_time, large_level)

        min_df['TradeTime'] = pd.to_datetime(min_df['TradeTime'])
        mid_df['TradeTime'] = pd.to_datetime(mid_df['TradeTime'])
        lar_df['TradeTime'] = pd.to_datetime(lar_df['TradeTime'])

        min_target_df = min_df[min_df['TradeTime'] <= min_test_time]
        mid_target_df = mid_df[mid_df['TradeTime'] <= mid_test_time]
        lar_target_df = lar_df[lar_df['TradeTime'] <= lar_test_time]

        price = mid_target_df['close'].values[-1]
        now = str(test_time)
    else:
        min_target_df = min_df = read4csv(symbol, min_level)
        mid_target_df = mid_df = read4csv(symbol, mid_level)
        lar_target_df = lar_df = read4csv(symbol, large_level)

    # print(lar_target_df.columns)
    print(price)
    # print(lar_target_df['close'].iloc[-1])
    # print(lar_target_df['EMA11'].iloc[-1])
    print(lar_target_df['BBANDS_Up'].iloc[-1])
    print(lar_target_df['BBANDS_Mid'].iloc[-1])
    print(lar_target_df['BBANDS_Low'].iloc[-1])
    # print(lar_target_df['MACD'].iloc[-1])
    # print(lar_target_df['Signal'].iloc[-1])
    # print(lar_target_df['Hist'].iloc[-1])
    # print(lar_target_df['ADX'].iloc[-1])
    # print(lar_target_df['DI+'].iloc[-1])
    # print(lar_target_df['DI-'].iloc[-1])
    # print(lar_target_df['FI'].iloc[-1])
    pre_lar_k = lar_target_df['Kcolor'].iloc[-2]
    pre_mid_k = mid_target_df['Kcolor'].iloc[-2]
    pre_min_k = min_target_df['Kcolor'].iloc[-2]
    lar_k = lar_target_df['Kcolor'].iloc[-1]
    mid_k = mid_target_df['Kcolor'].iloc[-1]
    min_k = min_target_df['Kcolor'].iloc[-1]
    mid_ema11 = mid_target_df['EMA11'].iloc[-1]
    mid_ema22 = mid_target_df['EMA22'].iloc[-1]
    mid_price4value = judge_price4value(price, mid_ema11, mid_ema22)
    # 大级别上升，水下+2，水上+1，做多，中级别：水下反转，red-后blue-，+2，水上red+后blue，+1，小级别金死叉判断和布林边界
    # 大级别下降，水上+2，水下+1，做空，中级别：水上反转，green+后blue+，+2，水下green-后blue，+1，
    # print("大级别K：")
    # print('\t', pre_lar_k)
    # print('\t', lar_k)
    # print("中级别K：")
    # print('\t', pre_mid_k)
    # print('\t', mid_k)
    # print("小级别K：")
    # print('\t', pre_min_k)
    # print('\t', min_k)
    # print()
    # print(mid_price4value)
    # print(mid_level, ' ', i)

    mid_distance_up2_1=mid_target_df["distance_up2"].iloc[-1]
    mid_distance_low2_1=mid_target_df["distance_low2"].iloc[-1]
    mid_distance_up2_2=mid_target_df["distance_up2"].iloc[-2]
    mid_distance_low2_2=mid_target_df["distance_low2"].iloc[-2]
    mid_distance_up2_3=mid_target_df["distance_up2"].iloc[-3]
    mid_distance_low2_3=mid_target_df["distance_low2"].iloc[-3]
    res_mdu = count_numbers(mid_distance_up2_1,mid_distance_up2_2,mid_distance_up2_3)
    res_mdl = count_numbers(mid_distance_low2_1,mid_distance_low2_2,mid_distance_low2_3)
    print(f"正数: {res_mdu[0]}, 负数: {res_mdu[1]}, 零: {res_mdu[2]}")
    print(f"正数: {res_mdl[0]}, 负数: {res_mdl[1]}, 零: {res_mdl[2]}")
    mid_up_is_away = check_price_away_bollinger(mid_target_df["distance_up2"])  # 降势，远离上轨
    mid_low_is_away = check_price_away_bollinger(mid_target_df["distance_low2"]) # 升势，远离下轨
    lar_up_is_away = check_price_away_bollinger(lar_target_df["distance_up2"])
    lar_low_is_away = check_price_away_bollinger(lar_target_df["distance_low2"])
    print(mid_up_is_away,mid_low_is_away)
    score = 0
    prompt = ''

    # 大级别前red，当前blue，如果水下blue-，则加2分，上升；反则是green+,blue+
    # 大级别前green，当前blue，如果水下green-，则加2分，上升；反则是red+,blue+
    # 中顺着大级别

    if ('red' not in mid_k) and ('red' not in lar_k):
        score = score + 2
        prompt = prompt + '{升势}大级别&中级别K都不为红；'
        if 'red' in pre_lar_k:
            score = score + 1
            prompt = prompt + '大级别前K为红色；'
        if 'red' in pre_mid_k:
            score = score + 1
            prompt = prompt + '中级别前K为红色；'
        if 'below_value_zone' == mid_price4value:
            score = score + 2
            prompt = prompt + '在价值区间下；'
        elif 'in_value_zone' == mid_price4value:
            score = score + 1
            prompt = prompt + '在价值区间中；'
        if lar_low_is_away is True :
            score = score + 1
            prompt = prompt + '大级别上远离下轨；'
        if mid_low_is_away is True :
            score = score + 1
            prompt = prompt + '中级别上远离下轨；'
        if 1 in min_target_df['cross'][-5:] :
            score = score + 1
            prompt = prompt + '小级别上前5K已经发生金叉；'
        if res_mdl[0] == 2:
            score = score + 1
            prompt = prompt + '中级别有一K超卖；'
        if res_mdl[0] == 1:
            score = score + 2
            prompt = prompt + '中级别有俩K超卖；'
        if res_mdl[0] == 0:
            score = score + 3
            prompt = prompt + '中级别有仨K超卖；'
    elif ('green' not in mid_k) and ('green' not in lar_k):
        score = score + 2
        prompt = prompt + '{降势}大级别&中级别K都不为绿；'
        if 'green' in pre_lar_k:
            score = score + 1
            prompt = prompt + '大级别前K为绿色；'
        if 'green' in pre_mid_k:
            score = score + 1
            prompt = prompt + '中级别前K为绿色；'
        if 'above_value_zone' == mid_price4value:
            score = score + 2
            prompt = prompt + '在价值区间上；'
        elif 'in_value_zone' == mid_price4value:
            score = score + 1
            prompt = prompt + '在价值区间中；'
        if lar_up_is_away is True:
            score = score + 1
            prompt = prompt + '大级别上，远离上轨；'
        if mid_up_is_away is True:
            score = score + 1
            prompt = prompt + '中级别上，远离上轨；'
        if -1 in min_target_df['cross'][-5:]:
            score = score + 1
            prompt = prompt + '小级别上前5K已经发生死叉；'
        if res_mdu[0] == 2:
            score = score + 1
            prompt = prompt + '中级别有一K超买；'
        if res_mdu[0] == 1:
            score = score + 2
            prompt = prompt + '中级别有俩K超买；'
        if res_mdu[0] == 0:
            score = score + 3
            prompt = prompt + '中级别有仨K超买；'
    else:
        prompt = prompt + '没有机会，观望。'



    imsg = f"{run_mod}环境，交易品种：{symbol},趋势判断：{prompt}||得分[{score}]，价格[{price}],周期模式：{level_str}，时间：{now},价格所处中级别位置#{mid_price4value}"
    print(imsg)

    if run_mod == 'test':
        print('测试时间：', test_time)
        if score >= 4:
            input('分值大于等于{4}，按键继续')
        # input('测试中，按任意键继续')
    else:
        print('等待', str(mid_level * 30), '秒')
        time.sleep(mid_level * 30)
